/**
 * @fileoverview   dom/size 获取元素大小，位置，滚动条等

 * @date: 11-11-4
 * @time: 上午10:33
 * @author 2kid
 * @version 0.001
 */


/**
 *
 * 方法：
 * dom.winsize
 * dom.docsize
 * dom.docscroll
 * dom.prototype.width
 * dom.prototype.height
 * dom.prototype.innerwidth
 * dom.prototype.outerwidth
 * dom.prototype.innerheight
 * dom.prototype.outerheight
 * dom.prototype.scroll
 * 方法：
 * dom.query
 *
 */
F.reg('dom/size', function (f, dom) {
    var win = window, doc = win['document'], docElement = doc.documentElement;


    f.extend(dom, {
        /**
         * @name F.Dom.winsize
         * @function
         * @namespace 获取窗口宽高
         * @return {Object}  {w:xx,h:xx}
         * @example
         * 例子：
         * 1.
         * dom.winsize();
         * //{w:1000,height:200}
         */
        winsize:function () {
            var o = {}, docElemProp;
            docElemProp = docElement['clientWidth'];
            o.w = doc.compatMode === 'CSS1Compat' && docElemProp ||
                doc.body['clientWidth'] || docElemProp;
            docElemProp = docElement['clientHeight'];
            o.h = doc.compatMode === 'CSS1Compat' && docElemProp ||
                doc.body['clientHeight'] || docElemProp;
            return o;
        },
        /**
         * @name F.Dom.docsize
         * @function
         * @namespace 获取文档宽高
         * @return {Object}  {w:xx,h:xx}
         * @example
         * 例子：
         * 1.
         * dom.docsize();
         * //{w:1000,height:200}
         */
        docsize:function () {
            return{
                w:Math.max(
                    docElement['clientWidth'],
                    doc.body['scrollWidth'], docElement['scrollWidth']
                ),
                h:Math.max(
                    docElement['clientHeight'],
                    doc.body['scrollHeight'], docElement['scrollHeight']
                )
            };
        },
        /**
         * @name F.Dom.docscroll
         * @function
         * @namespace 获取或设置 文档滚动条位置 {l:xx,t:xx}
         * @param o  格式，可选{l:xx,t:xx}
         * @return {Object}  {l:xx,t:xx}
         * @example
         * 例子：
         * 1.
         * dom.docscroll();
         * //{w:1000,height:200}
         * 2.
         * //设置文档滚动条    top : 100
         * dom.docscroll({t:100);
         */
        docscroll:function (o) {
            if (f.type(o, 'undefined')) {
                return {
                    l:document.documentElement.scrollLeft || document.body.scrollLeft,
                    t:document.documentElement.scrollTop || document.body.scrollTop
                }
            } else {
                if ('l' in o) {
                    document.documentElement.scrollLeft = o.l;
                    document.body.scrollLeft = o.l;
                }
                if ('t' in o) {
                    document.documentElement.scrollTop = o.t;
                    document.body.scrollTop = o.t;
                }
            }

        }
    }, true);
    f.extend(dom, {
        /**
         * @name F.Dom.prototype.width
         * @function
         * @namespace  获取第一个元素宽度
         * @return { Number}
         * @example
         * 例子：
         * 1.
         * //获取第一个元素宽度
         * dom.query('div').width();
         */
        width:function () {
            var ele = this.get(0);
            if(ele.nodeType===dom.NodeType.DOCUMENT_NODE){
                return dom.docsize().w;
            }else if(dom.iswin(ele)){
                return dom.winsize().w;
            }

            return this._size(ele, false, 'width');
        },
        /**
         * @name F.Dom.prototype.height
         * @function
         * @namespace  获取第一个元素高度
         * @return { Number}
         * @example
         * 例子：
         * 1.
         * //获取第一个元素高度
         * dom.query('div').height();
         */
        height:function () {
            var ele = this.get(0);
            if(ele.nodeType===dom.NodeType.DOCUMENT_NODE){
                return dom.docsize().h;
            }else if(dom.iswin(ele)){
                return dom.winsize().h;
            }

            return this._size(ele, false, 'height');
        },
        /**
         * @name F.Dom.prototype.innerwidth
         * @function
         * @namespace  获取第一个内部宽度，包含padding
         * @return { Number}
         * @example
         * 例子：
         * 1.
         * //获取第一个内部宽度，包含padding
         * dom.query('div').innerwidth();
         */
        innerwidth:function () {
            return this._size(this.get(0), 'inner', 'width');
        },
        /**
         * @name F.Dom.prototype.outerwidth
         * @function
         * @namespace  获取第一个外部宽度，包含padding，border
         * @param {Boolean} includeMargin 是否包含margin
         * @return { Number}
         * @example
         * 例子：
         * 1.
         * //获取第一个外部宽度，包含padding，border
         * dom.query('div').outerwidth();
         * 2.
         * //获取第一个外部宽度，包含padding，border，margin
         * dom.query('div').outerwidth(true);
         */
        outerwidth:function (includeMargin) {
            if (includeMargin === true) {
                return this._size(this.get(0), true, 'width');
            } else {
                return this._size(this.get(0), 'outer', 'width');
            }
        },
        /**
         * @name F.Dom.prototype.innerheight
         * @function
         * @namespace  获取第一个内部高度，包含padding
         * @return { Number}
         * @example
         * 例子：
         * 1.
         * //获取第一个内部高度，包含padding
         * dom.query('div').innerheight();
         */
        innerheight:function () {
            return this._size(this.get(0), 'inner', 'height');
        },
        /**
         * @name F.Dom.prototype.outerheight
         * @function
         * @namespace  获取第一个外部高度，包含padding，border
         * @param {Boolean} includeMargin 是否包含margin
         * @return { Number}
         * @example
         * 例子：
         * 1.
         * //获取第一个外部高度，包含padding，border
         * dom.query('div').outerheight();
         * 2.
         * //获取第一个外部高度，包含padding，border，margin
         * dom.query('div').outerheight(true);
         *
         */
        outerheight:function (includeMargin) {
            if (includeMargin === true) {
                return this._size(this.get(0), true, 'height');
            } else {
                return this._size(this.get(0), 'outer', 'height');
            }
        },
        _size:function (ele, p, d) {
            var dir = {'width':['left', 'right'], 'height':['top', 'bottom']};
            var oRect = ele.getBoundingClientRect(),
                tsize = oRect[dir[d][1]] - oRect[dir[d][0]];
            //outer*
            if (p === 'outer') {
                return  tsize;
            }
            //outer*(true)
            if (p === true) {
                return tsize + parseFloat(this.css('margin-' + dir[d][0])) + parseFloat(this.css('margin-' + dir[d][1]));
            }
            //inner*
            if (p === 'inner') {
                return tsize - parseFloat(this.css('border-' + dir[d][0] + '-' + d)) - parseFloat(this.css('border-' + dir[d][0] + '-' + d));
            }
            //width|height
            return parseFloat(this.css(d));

        },
        /**
         * @name F.Dom.prototype.offset
         * @function
         * @namespace  获取第一个元素位置或设置元素位置，不传参数，则获取
         * @param {Object} o 设置元素位置{l:32,t:34}
         * @param {Boolean} relwin 可选，是否相对窗口，默认相对文档
         * @return {Object} dom对象或 {l:xx,t:xx}
         * @example
         * 例子：
         * 1.
         * //获取一个a元素相对文档的位置
         * dom.query('a').offset();
         * // {l:100,t:100}
         * 2.
         * //获取一个a元素相对可视窗口的位置
         * dom.query('a').offset(true);
         * 1.
         * //设置一个a元素相对文档的位置
         * dom.query('a').offset({l:100});
         * // {l:100,t:100}
         * 2.
         * //设置一个a元素相对可视窗口的位置
         * dom.query('a').offset({l:100,t:100},true);
         */
        offset:function (o, relwin) {
            var ele = this.get(0),
                oRect = ele.getBoundingClientRect(),
                docscrll = dom.docscroll(),
                docl = relwin||o===true ? 0 : docscrll.l,
                doct = relwin||o===true ? 0 : docscrll.t,
                offset;
            if (f.type(o, 'object')) {
                this.each(function (el) {
                    var oldoffset = this.offset(relwin);
                    if (this.css('position') === 'static') {
                        el.style.position = 'relative';
                    }
                    if ('l' in o) {
                        el.style.left = parseFloat(this.css('left')) + o.l - oldoffset.l + 'px';
                    }
                    if ('t' in o) {
                        el.style.top = parseFloat(this.css('top')) + o.t - oldoffset.t + 'px';
                    }

                });
                return this;
            }

            if (typeof arguments.callee.offset != "number") {
                var temp = document.createElement("div");
                temp.style.cssText = "position:absolute;left:0;top:0;";
                document.body.appendChild(temp);
                arguments.callee.offset = -temp.getBoundingClientRect().top - docscrll.t;
                document.body.removeChild(temp);
                temp = null;
            }
            offset = arguments.callee.offset;
            return {
                l:oRect.left + offset + docl,
                t:oRect.top + offset + doct

            };

        },
        /**
         * @name F.Dom.prototype.scroll
         * @function
         * @namespace  获取或设置元素滚动条位置，不能获取文档的，文档的请直接使用 docscroll
         * @param {Object} o 可选，{ l:234,t:234}形式，可以只传一个。
         * @return {Object} dom对象或 {l:xx,t:xx}
         * @example
         * 例子：
         * 1.
         * @example
         * 例子：
         * 1.
         * dom.query('div').scroll();
         * //{w:1000,height:200}
         * 2.
         * //设置div滚动条    top : 100
         * dom.query('div').scroll({t:100);
         */
        scroll:function (o) {
            var ele = this.get(0);
            if(ele.nodeType===dom.NodeType.DOCUMENT_NODE){
                return dom.docscroll(o);
            }
            if (f.type(o, 'undefined')) {

                return {
                    l:ele.scrollLeft,
                    t:ele.scrollTop
                }
            } else {
                if ('l' in o) {
                    ele.scrollLeft = o.l;
                }
                if ('t' in o) {
                    ele.scrollTop = o.t;
                }
            }
            return this;
        }

    });


    return dom;
}, {
    requires:[
         'dom/css'
    ]

});